home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / documents / audio / audio.apps / dev / mixing < prev    next >
Encoding:
Internet Message Format  |  1996-11-11  |  8.6 KB

  1. Path: gazette.engr.sgi.com!candiru!cook
  2. From: cook@candiru.engr.sgi.com (Doug Cook)
  3. Newsgroups: comp.sys.sgi.misc
  4. Subject: Re: [Q] How to merge sounds by multiports ? [long]
  5. Date: 20 Apr 1995 16:16:34 GMT
  6. Organization: Silicon Graphics, Inc.  Mountain View, CA
  7. Lines: 143
  8. Message-ID: <3n61d2$cd0@gazette.engr.sgi.com>
  9. References: <3n2rd4$n1l@nuscc.nus.sg>
  10. NNTP-Posting-Host: candiru.engr.sgi.com
  11.  
  12. In article <3n2rd4$n1l@nuscc.nus.sg>, lulei@iscs.nus.sg writes:
  13. >    My question is how to play several sounds simultaneously. So I've got to
  14. > take care how to get these sounds together - merging - then send them to
  15. > the physical output port. I tried to use several same 'sproc' , with each
  16. > one, open a logical ALport that is different to the others. So you know, I
  17. > just send sound data to these ALports 'simultaneously', I expect they can
  18. > be mixed automatically by the advanced sound fascility of SGI.  However,
  19. > the result seems it doesn't work. The sounds played are cliped and lost
  20. > their most fidelities.
  21.  
  22. In general, using multiple ports isn't a great way to do mixing. It
  23. consumes more system resources and it's more difficult to synchronize
  24. the different sounds precisely. (You CAN do sample-accurate
  25. synchronization between multiple ports in the same direction; use the
  26. ALgetframenumber() call).
  27.  
  28. But the best way is to  mix the sounds together in your application,
  29. and write them into one port. Mixing isn't hard, but you need to choose
  30. the right algorithm.
  31.  
  32. Here's a little blurb on mixing. Well, perhaps not so little, but I wanted
  33. to explain the different approaches so you could pick one that works well
  34. for your problem.
  35.  
  36. The simplest mixing algorithm is just to add the sounds that you want to 
  37. play together. Suppose you have two sounds, A and B. For each sample of
  38. output, you add together the two corresponding input samples,
  39.     short a, b, mix;
  40.  
  41.     mix = a + b;
  42.  
  43. The trick with this, and with all mixing algorithms, is that you must
  44. be careful that the result does not overflow the numeric representation
  45. you are using. In other words, if A and B are both of type "short," and
  46. the result, mix,  is of type "short," you have the potential to
  47. overflow 16 bits. If A is 32767 and B is 1, then (A+B) in a 16-bit
  48. two's complement number is -32768. In effect, this creates a massive
  49. discontinuity in the output, because the signal "wraps around" from 32767
  50. to -32768.
  51.  
  52. To minimize this problem, you typically need to do your mixing into a
  53. data type with extra dynamic range, limit the result to the appropriate
  54. number of bits, and then stuff it into a smaller representation. The
  55. modified version of the previous pseudo-code is:
  56.     short a,b,mix;
  57.     int result;
  58.  
  59.     result = a + b;            /* mix won't overflow because it's more bits */
  60.     /*
  61.      * limit the sum before we go from 32->16 bits
  62.      */
  63.     if (result < -32768) {
  64.         result = -32768;
  65.     }
  66.     else if (result > 32767) {
  67.         result = 32767;
  68.     }
  69.     mix = result;            /* put the result into 16 bits */
  70.     
  71. Limiting will ensure that if your result does go out of range, it will not
  72. create massive discontinuities. Because of this, it's common practice in
  73. mixing algorithms. (Note that if you're mixing a number of signals together, 
  74. you don't have to limit on each addition, only on the final sum, unless you're doing
  75. enough 16-bit additions to overflow 32 bits).
  76.  
  77. However, even though limiting avoids clicks and pops, the sound will still get
  78. distorted if the sum is out of range, because the actual sum cannot be represented.
  79. This is probably what's happening when you open several audio ports and find
  80. that the mixed result "loses fidelity."
  81.  
  82. To avoid this problem, the mixing algorithm can scale the signals. There are
  83. several approaches to this. The simplest is to scale the sum of the signals.
  84. This preserves the relative amplitudes between the signals, but allows the result
  85. to be scaled to fit in the 16-bit output range. The equivalent version of the
  86. mixing code would be:
  87.     short a,b,mix;
  88.     int result;
  89.  
  90.     result = a + b;            /* mix won't overflow because it's more bits */
  91.     mix = (result >> 1);        /* divide by 2, put the result into 16 bits */
  92.  
  93. This approach is guaranteed not to overflow because we're dividing by
  94. 2; since we only have 2 16-bit signals, the result can't be more than
  95. 2*32767 or less than -2*32768, so after we divide by two, we don't have
  96. to limit the result. If we had 3 signals, we could divide by 3, and so
  97. on. However, this approach has some problems. First, it makes the
  98. sounds substantially quieter. If b = 0, then the output is a/2, meaning
  99. that we hear a much quieter version of a. Second, it loses some
  100. information.  Dividing by 2 essentially means that we go from an n-bit
  101. signal to a (n-1)-bit signal for each of the inputs. We lose a bit of
  102. precision: if the input signal was 101, the output will be 50, which
  103. introduces a quantization error of 0.5, since 101/2 is really 50.5.
  104.  
  105. The most general approach is to scale the input signals themselves.
  106. This is the "professional" approach,  and the most complicated. I'll
  107. show a version which assumes the inputs are in floating-point, but it
  108. can be done in fixed-point, too (see my note about floating-point and
  109. the MIPS processor).
  110.  
  111.     float a,b, result;
  112.     float scale_a, scale_b;
  113.     short mix;
  114.  
  115.     result = scale_a*a + scale_b*b;
  116.     /*
  117.      * limit the sum before we go from FP->16 bits.
  118.      */
  119.     if (result < -32768.0f) {
  120.         result = -32768.0f;
  121.     }
  122.     else if (result > 32767.0f) {
  123.         result = 32767.0f;
  124.     }
  125.     mix = result;        /* convert FP->16 bit integer */
  126.  
  127. [NOTE on floating-point and the MIPS processor. Contrary to traditional
  128. wisdom about microprocessors, floating-point multiplies tend to be much
  129. faster than integer multiplies on the MIPS processors. Therefore,
  130. signal-processing code often works best in floating-point. The trick
  131. is that converting your integer data to and from floating-point is
  132. costly. However, if you're doing more than one multiply on a given
  133. number, it's often worth the conversion.  Some guidelines:  a) Don't convert
  134. back and forth more than necessary.  b) Use the -mips2 flag on an R4XXX
  135. or higher if you don't need R3000 compatibility; this will make the
  136. FP->int conversion much faster. c) always use multiplies, not divides,
  137. if you can get away with it.]
  138.  
  139. The trick with this mixing algorithm is picking good values for scale_a and
  140. scale_b. These will depend upon the input signals. You want them as large
  141. as possible such that the sum of the input never overflows.
  142.  
  143. Some other notes, for the totally performance-minded:
  144.  
  145. 1. Limiting can be done more efficiently if you want to use the MIPSIV
  146. instruction set; it has conditional-move capabilities. This allows you
  147. to do the comparison without branching. Branching is always a performance
  148. hit since it requires the processor pipeline to be refilled.
  149.  
  150. 2. In general, an M-input-channel to N-output-channel mixer is an MxN
  151. matrix multiply. This is often a good way to think about mixing in the
  152. general case. I've gotten extremely good performance out of a
  153. floating-point matrix multiply algorithm for audio mixing.
  154.  
  155. Gints Klimanis <gints@sgi.com> adds that another "gotcha" on floating-
  156. point signal processing is the automatic promotion of some floating-point
  157. operands and arguments to double-precision. Double-precision 
  158. arithmetic is typically more costly than single-precision, so if you
  159. don't need it, make sure you're not using it. In some cases the 
  160. compiler will automatically promote operands to double-precision
  161. "behind your back." Here are some things to look for. Check out the 
  162. "-float" option on the C compiler, which instructs the compiler (in
  163. K&R mode) to avoid promoting operands to double-precision. It's also a 
  164. very good idea to use function prototypes with functions taking 
  165. "float" arguments -- otherwise the arguments will be promoted to 
  166. double-precision (even with the -float option). Finally, if a floating-point 
  167. constant is to be single-precision, it should be given in the form "0.0f", 
  168. i.e. explicitly single-precision, to avoid promotion to double-precision.
  169.  
  170.     -Doug
  171.     
  172.  
  173. Doug Cook, cook@sgi.com                 Silicon Graphics, Inc.
  174.  
  175. "Slab and Esther, uncomfortable with each other, stood in front of an easel in 
  176. his place, looking at Cheese Danish #35. The cheese danish was a recent 
  177. obsession of Slab's. He had taken some time ago to painting in a frenzy these
  178. morning-pastries in every conceivable style, light, and setting. The room was 
  179. already littered with Cubist, Fauve, and Surrealist cheese Danishes. 'Monet 
  180. spent his declining years at his home in Giverny, painting the water lilies in 
  181. the garden pool,' reasoned Slab.'He painted all kinds of water lilies. He liked
  182. water lilies. These are my declining years. I like cheese Danishes, they have
  183. kept me alive now for longer than I can remember. Why not.'" -Thomas Pynchon
  184.